package cn.iocoder.yudao.module.common.util.http;

import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.http.HttpException;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.Method;
import lombok.extern.slf4j.Slf4j;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.*;

import static cn.hutool.http.HttpUtil.toParams;
import static cn.hutool.http.HttpUtil.urlWithForm;

/**
 * HTTP 工具类 
 *
 * @author 芋道源码
 */
@Slf4j
public class HttpUtil {
    private static final int DEFAULT_TIMEOUT = 5000; // 默认超时时间，单位为毫秒
    private static final int DEFAULT_RETRY_TIMES = 3; // 默认请求重试次数
    // 默认最大连接数
    private static final int DEFAULT_MAX_CONNECTIONS = 100;
    // 默认不启用SSL验证
    private static final boolean DEFAULT_ENABLE_SSL = false;


    private static ExecutorService executorService; // 线程池
    private static Map<String, HttpRequest> httpRequestMap; // HttpRequest对象缓存
    static {
        // 初始化线程池和HttpRequest缓存
        int corePoolSize = 5;
        int maximumPoolSize = 10;
        long keepAliveTime = 60L;
        TimeUnit unit = TimeUnit.SECONDS;
        BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>(100);
        ThreadFactory threadFactory = Executors.defaultThreadFactory();
        RejectedExecutionHandler handler = new ThreadPoolExecutor.CallerRunsPolicy();

        ThreadPoolExecutor executorService = new ThreadPoolExecutor(
                corePoolSize,
                maximumPoolSize,
                keepAliveTime,
                unit,
                workQueue,
                threadFactory,
                handler
        );
        httpRequestMap = new HashMap<>();
    }
    // 发送GET请求

    /**
     * get请求
     * @param url 请求url
     * @param headerConfig 请求头
     * @param param 请求参数  自动转 xxx.com?parm=value&parm1=value2
     * @return reponse.body
     */
    public static String get(String url, HeaderConfig headerConfig,Map<String,String> param) {
        url = convertToUrlParam(url,param);
        return get(url, headerConfig, DEFAULT_TIMEOUT, DEFAULT_RETRY_TIMES);
    }

    // 发送GET请求
    /**
     * get请求
     * @param url 请求url
     * @param headerConfig 请求头
     * @return reponse.body
     */
    public static String get(String url, HeaderConfig headerConfig) {
        return get(url, headerConfig, DEFAULT_TIMEOUT, DEFAULT_RETRY_TIMES);
    }
    /**
     * POST请求
     * @param url 请求url
     * @param headerConfig 请求头
     * @param body 请求参数  自动转  parm=value&parm1=value2
     * @return reponse.body
     */
    public static String post(String url, HeaderConfig headerConfig, Map<String,String> body) {
        String bodyStr = body==null?"":toParams(body);
        return post(url, headerConfig, bodyStr, DEFAULT_TIMEOUT, DEFAULT_RETRY_TIMES);
    }
    // 发送POST请求
    /**
     * POST请求
     * @param url 请求url
     * @param headerConfig 请求头
     * @param body 请求参数  自动转 xxx.com?parm=value&parm1=value2
     * @return reponse.body
     */
    public static String post(String url, HeaderConfig headerConfig, String body) {
        return post(url, headerConfig, body, DEFAULT_TIMEOUT, DEFAULT_RETRY_TIMES);
    }
    // 发送GET请求
    public static String get(String url, HeaderConfig headerConfig, int timeout, int retryTimes) {
        HttpRequest request = createHttpRequest(url,Method.GET,headerConfig, timeout);
        return executeRequest(request, retryTimes);
    }

    // 发送POST请求
    public static String post(String url, HeaderConfig headerConfig, String body, int timeout, int retryTimes) {
        HttpRequest request = createHttpRequest(url, Method.POST,headerConfig, timeout);
        log.info("==============START ===================");
        log.info("请求url:"+request.getUrl());
        log.info("请求param:"+ body);
        String response = executeRequest(request.body(body), retryTimes);
        log.info("响应内容:"+ response);

        log.info("==============END===================");
        return response;
    }

    // 创建HttpRequest对象
    private static HttpRequest createHttpRequest(String url, Method methodType,HeaderConfig headerConfig, int timeout) {
        HttpRequest request = httpRequestMap.get(url);

        if (request == null) {
            request = HttpRequest.get(url);
            request.setMethod(methodType);
            if(headerConfig!=null){
                serHeader(headerConfig,request);

            }
            httpRequestMap.put(url, request);
        }
        request.timeout(timeout)
                .headerMap(headerConfig.getHeaders(),true)
                .setSSLSocketFactory(createSSLSocketFactory()) ;

        return request;
    }

    // 执行请求并返回响应结果
    private static String executeRequest(HttpRequest request, int retryTimes) {
        String response = null;
        int retryCount = 0;
        while (response == null && retryCount <= retryTimes) {
            try {
                response = request.execute().body();

            log.debug("响应内容:%s",response);
            } catch (HttpException e) {
                e.printStackTrace();
                retryCount++;
                if (retryCount <= retryTimes) {
                    // 休眠一段时间后进行重试
                    ThreadUtil.sleep(1000);
                }
            }
        }

        return response;
    }

    // 创建SSLSocketFactory对象
    private static SSLSocketFactory createSSLSocketFactory() {
        if (DEFAULT_ENABLE_SSL) {
            try {
                // 加载证书
                CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
                InputStream certStream = new FileInputStream("path/to/certificate.crt");
                X509Certificate certificate = (X509Certificate) certificateFactory.generateCertificate(certStream);

                // 创建KeyStore并设置证书
                KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
                keyStore.load(null, null);
                keyStore.setCertificateEntry("alias", certificate);

                // 创建TrustManagerFactory并初始化KeyStore
                TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
                trustManagerFactory.init(keyStore);

                // 创建SSLContext并设置TrustManager
                SSLContext sslContext = SSLContext.getInstance("TLS");
                sslContext.init(null, trustManagerFactory.getTrustManagers(), null);

                return sslContext.getSocketFactory();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    // 关闭线程池
    public static void shutdown() {
        executorService.shutdown();
    }

    /**
     * 设置自定义header
     * @param header
     * @param request
     */
    public static void serHeader(HeaderConfig header ,HttpRequest request){
        if(header==null ){
            return;
        }
        Map<String, String> headers = header.getHeaders();
        for (Map.Entry<String, String> entry : headers.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            request.header(key,value);
            // 处理键和值
        }
    }

    public static String convertToUrlParam(String url, Map<String, String> param) {
        if (param == null || param.isEmpty()) {
            return url;
        }

        String paramStr = toParams(param);
        String urlWithParams = urlWithForm(url, paramStr, CharsetUtil.CHARSET_UTF_8,false);
        return urlWithParams;
    }

}
